home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\ALIAS.C < prev    next >
Text File  |  1994-12-31  |  61KB  |  2,897 lines

  1. /*
  2.  * alias.c Handles command aliases for irc.c 
  3.  *
  4.  * Written By Michael Sandrof
  5.  *
  6.  * Copyright(c) 1990 
  7.  *
  8.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  9.  */
  10.  
  11. #ifndef lint
  12. static    char    rcsid[] = "@(#)$Id: alias.c,v 1.28 1994/10/15 23:11:03 mrg Stab $";
  13. #endif
  14.  
  15. #include "irc.h"
  16.  
  17. #include "alias.h"
  18. #include "status.h"
  19. #include "edit.h"
  20. #include "history.h"
  21. #include "vars.h"
  22. #include "ircaux.h"
  23. #include "server.h"
  24. #include "screen.h"
  25. #include "window.h"
  26. #include "input.h"
  27. #include "names.h"
  28. #include "server.h"
  29. #include "output.h"
  30. #include "names.h"
  31.  
  32. extern    char    *dcc_raw_listen();
  33. extern    char    *dcc_raw_connect();
  34.  
  35. extern    void    strmcat();
  36. extern    void    strmcat_ue();
  37.  
  38. extern    char    *FromUserHost;
  39.  
  40. extern    int    parse_number __P((char **));
  41. static    char    *next_unit __P((char *, char *, int *, int));
  42. static    long    randm();
  43.  
  44. static    char    *alias_detected();
  45. static    char    *alias_sent_nick();
  46. static    char    *alias_recv_nick();
  47. static    char    *alias_msg_body();
  48. static    char    *alias_joined_nick();
  49. static    char    *alias_public_nick();
  50. static    char    *alias_dollar();
  51. static    char    *alias_channel();
  52. static    char    *alias_server();
  53. static    char    *alias_query_nick();
  54. static    char    *alias_target();
  55. static    char    *alias_nick();
  56. static    char    *alias_invite();
  57. static    char    *alias_cmdchar();
  58. static    char    *alias_line();
  59. static    char    *alias_away();
  60. static    char    *alias_oper();
  61. static    char    *alias_chanop();
  62. static    char    *alias_modes();
  63. static    char    *alias_buffer();
  64. static    char    *alias_time();
  65. static    char    *alias_version();
  66. static    char    *alias_currdir();
  67. static    char    *alias_current_numeric();
  68. static    char    *alias_server_version();
  69.  
  70. typedef struct
  71. {
  72.     char    name;
  73.     char    *(*func)();
  74. }    BuiltIns;
  75.  
  76. static    FAR BuiltIns built_in[] =
  77. {
  78.     { '.',        alias_sent_nick },
  79.     { ',',        alias_recv_nick },
  80.     { ':',        alias_joined_nick },
  81.     { ';',        alias_public_nick },
  82.     { '$',        alias_dollar },
  83.     { 'A',        alias_away },
  84.     { 'B',        alias_msg_body },
  85.     { 'C',        alias_channel },
  86.     { 'D',        alias_detected },
  87. /*
  88.     { 'E' },
  89.     { 'F' },
  90.     { 'G' },
  91. */
  92.     { 'H',         alias_current_numeric },
  93.     { 'I',        alias_invite },
  94. /*
  95.     { 'J' },
  96. */
  97.     { 'K',        alias_cmdchar },
  98.     { 'L',        alias_line },
  99.     { 'M',        alias_modes },
  100.     { 'N',        alias_nick },
  101.     { 'O',        alias_oper },
  102.     { 'P',        alias_chanop },
  103.     { 'Q',        alias_query_nick },
  104.     { 'R',        alias_server_version },
  105.     { 'S',        alias_server },
  106.     { 'T',        alias_target },
  107.     { 'U',        alias_buffer },
  108.     { 'V',        alias_version },
  109.     { 'W',        alias_currdir },
  110. /*
  111.     { 'X' },
  112.     { 'Y' },
  113. */
  114.     { 'Z',        alias_time },
  115.     { (char) 0,     NULL }
  116. };
  117.  
  118.     char    FAR command_line[BIG_BUFFER_SIZE+1] = "";
  119.  
  120.     char    *function_left __P((char *));
  121.     char    *function_right __P((char *));
  122.     char    *function_mid __P((char *));
  123.     char    *function_rand __P((char *));
  124.     char    *function_srand __P((char *));
  125.     char    *function_time __P((char *));
  126.     char    *function_stime __P((char *));
  127.     char    *function_index __P((char *));
  128.     char    *function_rindex __P((char *));
  129.     char    *function_match __P((char *));
  130.     char    *function_rmatch __P((char *));
  131.     char    *function_userhost __P((char *));
  132.     char    *function_strip __P((char *));
  133.     char    *function_encode __P((unsigned char *));
  134.     char    *function_decode __P((unsigned char *));
  135.     char    *function_ischannel __P((char *));
  136.     char    *function_ischanop __P((char *));
  137.     char    *function_word __P((char *));
  138.     char    *function_winnum __P((char *));
  139.     char    *function_winnam __P((char *));
  140.     char    *function_connect __P((char *));
  141.     char    *function_listen __P((char *));
  142.     char    *function_tdiff __P((char *));
  143.     char    *function_toupper __P((char *));
  144.     char    *function_tolower __P((char *));
  145.     char    *function_channels __P((char *));
  146.     char    *function_servers __P((char *));
  147.     char    *function_curpos __P((char *));
  148.     char    *function_onchannel __P((char *));
  149.     char    *function_pid __P((char *));
  150.     char    *function_ppid __P((char *));
  151.     char    *function_chanusers __P((char *));
  152.     char    *function_strftime __P((char *));
  153.  
  154. typedef struct
  155. {
  156.     char    *name;
  157.     char    *(*func)();
  158. }    BuiltInFunctions;
  159.  
  160. static BuiltInFunctions    FAR built_in_functions[] =
  161. {
  162.     { "LEFT",        function_left },
  163.     { "RIGHT",        function_right },
  164.     { "MID",        function_mid },
  165.     { "RAND",        function_rand },
  166.     { "SRAND",        function_srand },
  167.     { "TIME",        function_time },
  168.     { "TDIFF",        function_tdiff },
  169.     { "STIME",        function_stime },
  170.     { "INDEX",        function_index },
  171.     { "RINDEX",        function_rindex },
  172.     { "MATCH",        function_match },
  173.     { "RMATCH",        function_rmatch },
  174.     { "USERHOST",        function_userhost },
  175.     { "STRIP",        function_strip },
  176.     { "ENCODE",        function_encode },
  177.     { "DECODE",        function_decode },
  178.     { "ISCHANNEL",        function_ischannel },
  179.     { "ISCHANOP",        function_ischanop },
  180.     { "WORD",        function_word },
  181.     { "WINNUM",        function_winnum },
  182.     { "WINNAM",        function_winnam },
  183.     { "CONNECT",        function_connect },
  184.     { "LISTEN",        function_listen },
  185.     { "TOUPPER",        function_toupper },
  186.     { "TOLOWER",        function_tolower },
  187.     { "MYCHANNELS",        function_channels },
  188.     { "MYSERVERS",        function_servers },
  189.     { "CURPOS",        function_curpos },
  190.     { "ONCHANNEL",        function_onchannel },
  191.     { "PID",        function_pid },
  192.     { "PPID",        function_ppid },
  193.     { "CHANUSERS",        function_chanusers },
  194.     { "STRFTIME",        function_strftime },
  195.     { (char *) 0,        NULL }
  196. };
  197.  
  198. /* alias_illegals: characters that are illegal in alias names */
  199.     char    alias_illegals[] = " #+-*/\\()={}[]<>!@$%^~`,?;:|'\"";
  200.  
  201. static    Alias    *alias_list[] =
  202. {
  203.     (Alias *) 0,
  204.     (Alias *) 0
  205. };
  206.  
  207. /* alias_string: the thing that gets replaced by the $"..." construct */
  208. static    char    *alias_string = (char *) 0;
  209.  
  210. static    int    eval_args;
  211.  
  212. /* function_stack and function_stkptr - hold the return values from functions */
  213. static    char    * FAR function_stack[128] =
  214.     (char *) 0
  215. };
  216. static    int    function_stkptr = 0;
  217.  
  218. extern    char    *MatchingBracket();
  219.  
  220. /*
  221.  * find_alias: looks up name in in alias list.  Returns the Alias    entry if
  222.  * found, or null if not found.   If unlink is set, the found entry is
  223.  * removed from the list as well.  If match is null, only perfect matches
  224.  * will return anything.  Otherwise, the number of matches will be returned. 
  225.  */
  226. static    Alias    *
  227. find_alias(list, name, unlink, match)
  228.     Alias    **list;
  229.     char    *name;
  230.     int    unlink;
  231.     int    *match;
  232. {
  233.     Alias    *tmp,
  234.         *last = (Alias *) 0;
  235.     int    cmp,
  236.         len;
  237.     int    (*cmp_func)();
  238.  
  239.     if (match)
  240.     {
  241.         *match = 0;
  242.         cmp_func = my_strnicmp;
  243.     }
  244.     else
  245.         cmp_func = my_stricmp;
  246.     if (name)
  247.     {
  248.         len = strlen(name);
  249.         for (tmp = *list; tmp; tmp = tmp->next)
  250.         {
  251.             if ((cmp = cmp_func(name, tmp->name, len)) == 0)
  252.             {
  253.                 if (unlink)
  254.                 {
  255.                     if (last)
  256.                         last->next = tmp->next;
  257.                     else
  258.                         *list = tmp->next;
  259.                 }
  260.                 if (match)
  261.                 {
  262.                     (*match)++;
  263.                     if (strlen(tmp->name) == len)
  264.                     {
  265.                         *match = 0;
  266.                         return (tmp);
  267.                     }
  268.                 }
  269.                 else
  270.                     return (tmp);
  271.             }
  272.             else if (cmp < 0)
  273.                 break;
  274.             last = tmp;
  275.         }
  276.     }
  277.     if (match && (*match == 1))
  278.         return (last);
  279.     else
  280.         return ((Alias *) 0);
  281. }
  282.  
  283. /*
  284.  * insert_alias: adds the given alias to the alias list.  The alias list is
  285.  * alphabetized by name 
  286.  */
  287. static    void    
  288. insert_alias(list, alias)
  289.     Alias    **list;
  290.     Alias    *alias;
  291. {
  292.     Alias    *tmp,
  293.         *last,
  294.         *foo;
  295.  
  296.     last = (Alias *) 0;
  297.     for (tmp = *list; tmp; tmp = tmp->next)
  298.     {
  299.         if (strcmp(alias->name, tmp->name) < 0)
  300.             break;
  301.         last = tmp;
  302.     }
  303.     if (last)
  304.     {
  305.         foo = last->next;
  306.         last->next = alias;
  307.         alias->next = foo;
  308.     }
  309.     else
  310.     {
  311.         alias->next = *list;
  312.         *list = alias;
  313.     }
  314. }
  315.  
  316. /*
  317.  * add_alias: given the alias name and "stuff" that makes up the alias,
  318.  * add_alias() first checks to see if the alias name is already in use... if
  319.  * so, the old alias is replaced with the new one.  If the alias is not
  320.  * already in use, it is added. 
  321.  */
  322. void    
  323. add_alias(type, name, stuff)
  324.     int    type;
  325.     char    *name,
  326.         *stuff;
  327. {
  328.     Alias    *tmp;
  329.     char    *ptr;
  330.  
  331.     upper(name);
  332.     if (type == COMMAND_ALIAS)
  333.         say("Alias    %s added", name);
  334.     else
  335.     {
  336.         if (!strcmp(name, "FUNCTION_RETURN"))
  337.         {
  338.             if (function_stack[function_stkptr])
  339.                 new_free(&function_stack[function_stkptr]);
  340.             malloc_strcpy(&function_stack[function_stkptr], stuff);
  341.             return;
  342.         }
  343.         if ((ptr = sindex(name, alias_illegals)) != NULL)
  344.         {
  345.             yell("Assign names may not contain '%c'", *ptr);
  346.             return;
  347.         }
  348.         say("Assign %s added", name);
  349.     }
  350.     if ((tmp = find_alias(&(alias_list[type]), name, 1, (int *) 0)) ==
  351.             (Alias *) 0)
  352.     {
  353.         tmp = (Alias *) new_malloc(sizeof(Alias));
  354.         if (tmp == (Alias *) 0)
  355.         {
  356.             yell("Couldn't allocate memory for new alias!");
  357.             return;
  358.         }
  359.         tmp->name = (char *) 0;
  360.         tmp->stuff = (char *) 0;
  361.     }
  362.     malloc_strcpy(&(tmp->name), name);
  363.     malloc_strcpy(&(tmp->stuff), stuff);
  364.     tmp->mark = 0;
  365.     tmp->global = loading_global;
  366.     insert_alias(&(alias_list[type]), tmp);
  367. }
  368.  
  369. /* alias_arg: a special version of next_arg for aliases */
  370. static    char    *
  371. alias_arg(str, pos)
  372.     char    **str;
  373.     u_int    *pos;
  374. {
  375.     char    *ptr;
  376.  
  377.     if (!*str)
  378.         return (char *) 0;
  379.     *pos = 0;
  380.     ptr = *str;
  381.     while (' ' == *ptr)
  382.     {
  383.         ptr++;
  384.         (*pos)++;
  385.     }
  386.     if (*ptr == '\0')
  387.     {
  388.         *str = empty_string;
  389.         return ((char *) 0);
  390.     }
  391.     if ((*str = sindex(ptr, " ")) != NULL)
  392.         *((*str)++) = '\0';
  393.     else
  394.         *str = empty_string;
  395.     return (ptr);
  396. }
  397.  
  398. /* word_count: returns the number of words in the given string */
  399. extern    int    
  400. word_count(str)
  401.     char    *str;
  402. {
  403.     int    cnt = 0;
  404.     char    *ptr;
  405.  
  406.     while (1)
  407.     {
  408.         if ((ptr = sindex(str, "^ ")) != NULL)
  409.         {
  410.             cnt++;
  411.             if ((str = sindex(ptr, " ")) == (char *) 0)
  412.                 return (cnt);
  413.         }
  414.         else
  415.             return (cnt);
  416.     }
  417. }
  418.  
  419. static    char    *
  420. built_in_alias(c)
  421.     char    c;
  422. {
  423.     BuiltIns    *tmp;
  424.     char    *ret = (char *) 0;
  425.  
  426.     for(tmp = built_in;tmp->name;tmp++)
  427.         if (c == tmp->name)
  428.         {
  429.             malloc_strcpy(&ret, tmp->func());
  430.             break;
  431.         }
  432.     return(ret);
  433. }
  434.  
  435. /*
  436.  * find_inline: This simply looks up the given str.  It first checks to see
  437.  * if its a user variable and returns it if so.  If not, it checks to see if
  438.  * it's an IRC variable and returns it if so.  If not, it checks to see if
  439.  * its and environment variable and returns it if so.  If not, it returns
  440.  * null.  It mallocs the returned string 
  441.  */
  442. static    char    *
  443. find_inline(str)
  444.     char    *str;
  445. {
  446.     Alias    *alias;
  447.     char    *ret = NULL;
  448.     char    *tmp;
  449.  
  450.     if ((alias = find_alias(&(alias_list[VAR_ALIAS]), str, 0, (int *) NULL))
  451.             != NULL)
  452.     {
  453.         malloc_strcpy(&ret, alias->stuff);
  454.         return (ret);
  455.     }
  456.     if ((strlen(str) == 1) && (ret = built_in_alias(*str)))
  457.         return(ret);
  458.     if ((ret = make_string_var(str)) != NULL)
  459.         return (ret);
  460. #ifdef DAEMON_UID
  461.     if (getuid() == DAEMON_UID)
  462.     malloc_strcpy(&ret, (getuid() != DAEMON_UID) && (tmp = getenv(str)) ?
  463.                 tmp : empty_string);
  464. #else
  465.     malloc_strcpy(&ret, (tmp = getenv(str)) ? tmp : empty_string);
  466. #endif /* DAEMON_UID */
  467.     return (ret);
  468. }
  469.  
  470. static    char    *
  471. call_function(name, f_args, args, args_flag)
  472.     char    *name,
  473.         *f_args,
  474.         *args;
  475.     int    *args_flag;
  476. {
  477.     char    *tmp;
  478.     char    *result = (char *) 0;
  479.     char    *sub_buffer = (char *) 0;
  480.     int    builtnum;
  481.     char    *debug_copy = (char *) 0;
  482.  
  483.     tmp = expand_alias((char *) 0, f_args, args, args_flag, NULL);
  484.     if (get_int_var(DEBUG_VAR) & DEBUG_FUNCTIONS)
  485.         malloc_strcpy(&debug_copy, tmp);
  486.     for (builtnum = 0; built_in_functions[builtnum].name != NULL &&
  487.             my_stricmp(built_in_functions[builtnum].name, name);
  488.             builtnum++)
  489.         ;
  490.     if (built_in_functions[builtnum].name)
  491.         result = built_in_functions[builtnum].func(tmp);
  492.     else
  493.     {
  494.         sub_buffer = new_malloc(strlen(name)+strlen(tmp)+2);
  495.         strcpy(sub_buffer, name);
  496.         strcat(sub_buffer, " ");
  497.         strcat(sub_buffer, tmp);
  498.         function_stack[++function_stkptr] = (char *) 0;
  499.         parse_command(sub_buffer, 0, empty_string);
  500.         new_free(&sub_buffer);
  501.         eval_args=1;
  502.         result = function_stack[function_stkptr];
  503.         function_stack[function_stkptr] = (char *) 0;
  504.         if (!result)
  505.             malloc_strcpy(&result, empty_string);
  506.         function_stkptr--;
  507.     }
  508.     if (debug_copy)
  509.     {
  510.         yell("Function %s(%s) returned %s",
  511.             name, debug_copy, result);
  512.         new_free(&debug_copy);
  513.     }
  514.     new_free(&tmp);
  515.     return result;
  516. }
  517.  
  518.  
  519. /* Given a pointer to an operator, find the last operator in the string */
  520. char    *
  521. lastop(ptr)
  522.     char    *ptr;
  523. {
  524.     while (ptr[1] && index("!=<>&^|#+/-*", ptr[1]))
  525.         ptr++;
  526.     return ptr;
  527. }
  528.  
  529. #define    NU_EXPR    0
  530. #define    NU_CONJ NU_EXPR
  531. #define    NU_ASSN    1
  532. #define    NU_COMP 2
  533. #define    NU_ADD  3
  534. #define    NU_MULT 4
  535. #define    NU_UNIT 5
  536. #define    NU_TERT 6
  537. #define    NU_BITW 8
  538.  
  539. static    char    *
  540. next_unit(str, args, arg_flag, stage)
  541.     char    *str,
  542.         *args;
  543.     int    *arg_flag,
  544.         stage;
  545. {
  546.     char    *ptr,
  547.         *ptr2,
  548.         *right;
  549.     int    got_sloshed = 0;
  550.     char    *lastc;
  551.     char    tmp[40];
  552.     char    *result1 = (char *) 0,
  553.         *result2 = (char *) 0;
  554.     long    value1 = 0,
  555.         value2,
  556.         value3;
  557.     char    op;
  558.     int    display;
  559.     char    *ArrayIndex,
  560.         *EndIndex;
  561.  
  562.     while (isspace(*str))
  563.         ++str;
  564.     if (!*str)
  565.     {
  566.         malloc_strcpy(&result1, empty_string);
  567.         return result1;
  568.     }
  569.     lastc = str+strlen(str)-1;
  570.     while (isspace(*lastc))
  571.         *lastc-- = '\0';
  572.     if (stage == NU_UNIT && *lastc == ')' && *str == '(')
  573.     {
  574.         str++, *lastc-- = '\0';
  575.         return next_unit(str, args, arg_flag, NU_EXPR);
  576.     }
  577.     if (!*str)
  578.     {
  579.         malloc_strcpy(&result1, empty_string);
  580.         return result1;
  581.     }
  582.     for (ptr = str; *ptr; ptr++)
  583.     {
  584.         if (got_sloshed) /* Help! I'm drunk! */
  585.         {
  586.             got_sloshed = 0;
  587.             continue;
  588.         }
  589.         switch(*ptr)
  590.         {
  591.         case '\\':
  592.             got_sloshed = 1;
  593.             continue;
  594.         case '(':
  595.             if (stage != NU_UNIT || ptr == str)
  596.             {
  597.                 if (!(ptr2 = MatchingBracket(ptr+1, '(', ')')))
  598.                     ptr = ptr+strlen(ptr)-1;
  599.                 else
  600.                     ptr = ptr2;
  601.                 break;
  602.             }
  603.             *ptr++ = '\0';
  604.             right = ptr;
  605.             ptr = MatchingBracket(right, LEFT_PAREN, RIGHT_PAREN);
  606.             if (ptr)
  607.                 *ptr++ = '\0';
  608.             result1 = call_function(str, right, args, arg_flag);
  609.             if (ptr && *ptr)
  610.             {
  611.                 malloc_strcat(&result1, ptr);
  612.                 result2 = next_unit(result1, args, arg_flag,
  613.                         stage);
  614.                 new_free(&result1);
  615.                 result1 = result2;
  616.             }
  617.             return result1;
  618.         case '[':
  619.             if (stage != NU_UNIT)
  620.             {
  621.                 if (!(ptr2 = MatchingBracket(ptr+1, '[', ']')))
  622.                     ptr = ptr+strlen(ptr)-1;
  623.                 else
  624.                     ptr = ptr2;
  625.                 break;
  626.             }
  627.             *ptr++ = '\0';
  628.             right = ptr;
  629.             ptr = MatchingBracket(right, LEFT_BRACKET, RIGHT_BRACKET);
  630.             if (ptr)
  631.                 *ptr++ = '\0';
  632.             result1 = expand_alias((char *) 0, right, args, arg_flag, NULL);
  633.             if (*str)
  634.             {
  635.                 result2 = new_malloc(strlen(str)+
  636.                         (result1?strlen(result1):0)+
  637.                         (ptr?strlen(ptr):0) + 2);
  638.                 strcpy(result2, str);
  639.                 strcat(result2, ".");
  640.                 strcat(result2, result1);
  641.                 new_free(&result1);
  642.                 if (ptr && *ptr)
  643.                 {
  644.                     strcat(result2, ptr);
  645.                     result1 = next_unit(result2, args,
  646.                         arg_flag, stage);
  647.                 }
  648.                 else
  649.                 {
  650.                     result1 = find_inline(result2);
  651.                     if (!result1)
  652.                         malloc_strcpy(&result1,
  653.                             empty_string);
  654.                 }
  655.                 new_free(&result2);
  656.             }
  657.             else if (ptr && *ptr)
  658.             {
  659.                 malloc_strcat(&result1, ptr);
  660.                 result2 = next_unit(result1, args, arg_flag,
  661.                     stage);
  662.                 new_free(&result1);
  663.                 result1 = result2;
  664.             }
  665.             return result1;
  666.         case '-':
  667.         case '+':
  668.                         if (*(ptr+1) == *(ptr))  /* index operator */
  669.                         {
  670.                                 char *tptr;
  671.  
  672.                                 *ptr++ = '\0';
  673.                 if (ptr == str + 1)    /* Its a prefix */
  674.                                 {
  675.                                         tptr = str + 2;
  676.                                 }
  677.                 else            /* Its a postfix */
  678.                                 {
  679.                                         tptr = str;
  680.                                 }
  681.                     result1 = find_inline(tptr);
  682.                                 if (!result1) 
  683.                                         malloc_strcpy(&result1,"0");
  684.  
  685.                                 {           /* This isnt supposed to be
  686.                                                 attached to the if, so
  687.                                                 dont "fix" it. */
  688.                                         int r;
  689.                                         r = atoi(result1);
  690.                                         if (*ptr == '+')
  691.                                                 r++;
  692.                                         else    r--;
  693.                                         sprintf(tmp,"%ld",r);
  694.                                         display = window_display;
  695.                                         window_display = 0;
  696.                                         add_alias(VAR_ALIAS,tptr,tmp);
  697.                                         window_display = display;
  698.                                 }
  699.         /* A kludge?  Cheating?  Maybe.... */
  700.                 if (ptr == str + 1) 
  701.                 {
  702.                                     *(ptr-1) = ' ';
  703.                     *ptr = ' ';
  704.                 } else            
  705.                 {
  706.                                         if (*ptr == '+')
  707.                             *(ptr-1) = '-';
  708.                                         else
  709.                                                 *(ptr-1) = '+';
  710.                     *ptr = '1';
  711.                 }
  712.                                 ptr = str; 
  713.                                 new_free(&result1);
  714.                                 break;
  715.                         }
  716.             if (ptr == str) /* It's unary..... do nothing */
  717.                 break;
  718.             if (stage != NU_ADD)
  719.             {
  720.                 ptr = lastop(ptr);
  721.                 break;
  722.             }
  723.             op = *ptr;
  724.             *ptr++ = '\0';
  725.             result1 = next_unit(str, args, arg_flag, stage);
  726.             result2 = next_unit(ptr, args, arg_flag, stage);
  727.             value1 = atol(result1);
  728.             value2 = atol(result2);
  729.             new_free(&result1);
  730.             new_free(&result2);
  731.             if (op == '-')
  732.                 value3 = value1 - value2;
  733.             else
  734.                 value3 = value1 + value2;
  735.             sprintf(tmp, "%ld", value3);
  736.             malloc_strcpy(&result1, tmp);
  737.             return result1;
  738.         case '/':
  739.         case '*':
  740.           case '%':
  741.             if (stage != NU_MULT)
  742.             {
  743.                 ptr = lastop(ptr);
  744.                 break;
  745.             }
  746.             op = *ptr;
  747.             *ptr++ = '\0';
  748.             result1 = next_unit(str, args, arg_flag, stage);
  749.             result2 = next_unit(ptr, args, arg_flag, stage);
  750.             value1 = atol(result1);
  751.             value2 = atol(result2);
  752.             new_free(&result1);
  753.             new_free(&result2);
  754.             if (op == '/')
  755.             {
  756.                 if (value2)
  757.                     value3 = value1 / value2;
  758.                 else
  759.                 {
  760.                     value3 = 0;
  761.                     say("Division by zero");
  762.                 }
  763.             }
  764.             else
  765.                         if (op == '*')
  766.                 value3 = value1 * value2;
  767.                         else
  768.                         {
  769.                                 if (value2)
  770.                                     value3 = value1 % value2;
  771.                                 else
  772.                                 {
  773.                                         value3 = 0;
  774.                                         say("Mod by zero");
  775.                                 }
  776.                         }
  777.             sprintf(tmp, "%ld", value3);
  778.             malloc_strcpy(&result1, tmp);
  779.             return result1;
  780.         case '#':
  781.             if (stage != NU_ADD || ptr[1] != '#')
  782.             {
  783.                 ptr = lastop(ptr);
  784.                 break;
  785.             }
  786.             *ptr = '\0';
  787.             ptr += 2;
  788.             result1 = next_unit(str, args, arg_flag, stage);
  789.             result2 = next_unit(ptr, args, arg_flag, stage);
  790.             malloc_strcat(&result1, result2);
  791.             new_free(&result2);
  792.             return result1;
  793.     /* Reworked - Jeremy Nelson, Feb 1994
  794.      * & or && should both be supported, each with different
  795.      * stages, same with || and ^^.  Also, they should be
  796.      * short-circuit as well.
  797.      */
  798.         case '&':
  799.             if (ptr[0] == ptr[1])
  800.             {
  801.                 if (stage != NU_CONJ)
  802.                 {
  803.                     ptr = lastop(ptr);
  804.                     break;
  805.                 }
  806.                 *ptr = '\0';
  807.                 ptr += 2;
  808.                 result1 = next_unit(str, args, arg_flag, stage);
  809.                 value1 = atol(result1);
  810.                 if (value1)
  811.                 {
  812.                     result2 = next_unit(ptr, args, arg_flag, stage);
  813.                     value2 = atol(result2);
  814.                     value3 = value1 && value2;
  815.                 }
  816.                 else
  817.                     value3 = 0;
  818.                 new_free(&result1);
  819.                 new_free(&result2);
  820.                                 tmp[0] = '0' + (value3?1:0);
  821.                                 tmp[1] = '\0';
  822.                 malloc_strcpy(&result1, tmp);
  823.                  return result1;
  824.             }
  825.             else
  826.             {
  827.                 if (stage != NU_BITW)
  828.                 {
  829.                     ptr = lastop(ptr);
  830.                     break;
  831.                 }
  832.                 *ptr = '\0';
  833.                 ptr += 1;
  834.                 result1 = next_unit(str, args, arg_flag, stage);
  835.                 result2 = next_unit(ptr, args, arg_flag, stage);
  836.                 value1 = atol(result1);
  837.                 value2 = atol(result2);
  838.                 new_free(&result1);
  839.                 new_free(&result2);
  840.                 value3 = value1 & value2;
  841.                                 sprintf(tmp, "%ld",value3);
  842.                 malloc_strcpy(&result1, tmp);
  843.                  return result1;
  844.             }
  845.         case '|':
  846.             if (ptr[0] == ptr[1])
  847.             {
  848.                 if (stage != NU_CONJ)
  849.                 {
  850.                     ptr = lastop(ptr);
  851.                     break;
  852.                 }
  853.                 *ptr = '\0';
  854.                 ptr += 2;
  855.                 result1 = next_unit(str, args, arg_flag, stage);
  856.                 value1 = atol(result1);
  857.                 if (!value1)
  858.                 {
  859.                     result2 = next_unit(ptr, args, arg_flag, stage);
  860.                     value2 = atol(result2);
  861.                     value3 = value1 || value2;
  862.                 }
  863.                 else    
  864.                     value3 = 1;
  865.                 new_free(&result1);
  866.                 new_free(&result2);
  867.                 tmp[0] = '0' + (value3 ? 1 : 0);
  868.                 tmp[1] = '\0';
  869.                 malloc_strcpy(&result1, tmp);
  870.                  return result1;
  871.             }
  872.             else
  873.             {
  874.                 if (stage != NU_BITW)
  875.                 {
  876.                     ptr = lastop(ptr);
  877.                     break;
  878.                 }
  879.                 *ptr = '\0';
  880.                 ptr += 1;
  881.                 result1 = next_unit(str, args, arg_flag, stage);
  882.                 result2 = next_unit(ptr, args, arg_flag, stage);
  883.                 value1 = atol(result1);
  884.                 value2 = atol(result2);
  885.                 new_free(&result1);
  886.                 new_free(&result2);
  887.                 value3 = value1 | value2;
  888.                                 sprintf(tmp, "%ld",value3);
  889.                 malloc_strcpy(&result1, tmp);
  890.                  return result1;
  891.             }
  892.         case '^':
  893.             if (ptr[0] == ptr[1])
  894.             {
  895.                 if (stage != NU_CONJ)
  896.                 {
  897.                     ptr = lastop(ptr);
  898.                     break;
  899.                 }
  900.                 *ptr = '\0';
  901.                 ptr += 2;
  902.                 result1 = next_unit(str, args, arg_flag, stage);
  903.                 result2 = next_unit(ptr, args, arg_flag, stage);
  904.                 value1 = atol(result1);
  905.                 value2 = atol(result2);
  906.                 value1 = value1?1:0;
  907.                 value2 = value2?1:0;
  908.                 value3 = value1 ^ value2;
  909.                 new_free(&result1);
  910.                 new_free(&result2);
  911.                 tmp[0] = '0' + (value3 ? 1 : 0);
  912.                 tmp[1] = '\0';
  913.                 malloc_strcpy(&result1, tmp);
  914.                  return result1;
  915.             }
  916.             else
  917.             {
  918.                 if (stage != NU_BITW)
  919.                 {
  920.                     ptr = lastop(ptr);
  921.                     break;
  922.                 }
  923.                 *ptr = '\0';
  924.                 ptr += 1;
  925.                 result1 = next_unit(str, args, arg_flag, stage);
  926.                 result2 = next_unit(ptr, args, arg_flag, stage);
  927.                 value1 = atol(result1);
  928.                 value2 = atol(result2);
  929.                 new_free(&result1);
  930.                 new_free(&result2);
  931.                 value3 = value1 ^ value2;
  932.                                 sprintf(tmp, "%ld",value3);
  933.                 malloc_strcpy(&result1, tmp);
  934.                  return result1;
  935.             }
  936.                 case '?':
  937.                         if (stage != NU_TERT)
  938.                         {
  939.                 ptr = lastop(ptr);
  940.                 break;
  941.             }
  942.             *ptr++ = '\0';
  943.             result1 = next_unit(str, args, arg_flag, stage);
  944.             ptr2 = index(ptr, ':');
  945.             *ptr2++ = '\0';
  946.                         right = result1;
  947.                         value1 = parse_number(&right);
  948.                         if ((value1 == -1) && (*right == (char) 0))
  949.                                 value1 = 0;
  950.                         if ( value1 == 0 )
  951.                                 while (isspace(*right))
  952.                                         *(right++) = '\0';
  953.                         if ( value1 || *right )
  954.                 result2 = next_unit(ptr, args, arg_flag, stage);
  955.             else
  956.                 result2 = next_unit(ptr2, args, arg_flag, stage);
  957.                         *(ptr2-1) = ':';
  958.             new_free(&result1);
  959.             return result2;
  960.         case '=':
  961.             if (ptr[1] != '=')
  962.             {
  963.                 if (stage != NU_ASSN)
  964.                 {
  965.                     ptr = lastop(ptr);
  966.                     break;
  967.                 }
  968.                 *ptr++ = '\0';
  969.                 result1 = expand_alias((char *) 0, str,
  970.                     args, arg_flag, NULL);
  971.                 result2 = next_unit(ptr, args, arg_flag, stage);
  972.                 display = window_display;
  973.                 window_display = 0;
  974.                 lastc = result1 + strlen(result1) - 1;
  975.                 while (lastc > result1 && *lastc == ' ')
  976.                     *lastc-- = '\0';
  977.                 for (ptr = result1; *ptr == ' '; ptr++);
  978.                 while ((ArrayIndex = (char *) index(ptr, '['))
  979.                         != NULL)
  980.                 {
  981.                     *ArrayIndex++='.';
  982.                     if ((EndIndex = MatchingBracket(ArrayIndex,
  983.                         LEFT_BRACKET, RIGHT_BRACKET)) != NULL)
  984.                     {
  985.                         *EndIndex++='\0';
  986.                         strcat(ptr, EndIndex);
  987.                     }
  988.                     else
  989.                         break;
  990.                 }
  991.                 if (*ptr)
  992.                     add_alias(VAR_ALIAS, ptr, result2);
  993.                 else
  994.                     yell("Invalid assignment expression");
  995.                 window_display = display;
  996.                 new_free(&result1);
  997.                 return result2;
  998.             }
  999.             if (stage != NU_COMP)
  1000.             {
  1001.                 ptr = lastop(ptr);
  1002.                 break;
  1003.             }
  1004.             *ptr = '\0';
  1005.             ptr += 2;
  1006.             result1 = next_unit(str, args, arg_flag, stage);
  1007.             result2 = next_unit(ptr, args, arg_flag, stage);
  1008.             if (!my_stricmp(result1, result2))
  1009.                 malloc_strcpy(&result1, "1");
  1010.             else
  1011.                 malloc_strcpy(&result1, "0");
  1012.             new_free(&result2);
  1013.             return result1;
  1014.         case '>':
  1015.         case '<':
  1016.             if (stage != NU_COMP)
  1017.             {
  1018.                 ptr = lastop(ptr);
  1019.                 break;
  1020.             }
  1021.             op = *ptr;
  1022.             if (ptr[1] == '=')
  1023.                 value3 = 1, *ptr++ = '\0';
  1024.             else
  1025.                 value3 = 0;
  1026.             *ptr++ = '\0';
  1027.             result1 = next_unit(str, args, arg_flag, stage);
  1028.             result2 = next_unit(ptr, args, arg_flag, stage);
  1029.             if (isdigit(*result1) && isdigit(*result2))
  1030.             {
  1031.                 value1 = atol(result1);
  1032.                 value2 = atol(result2);
  1033.                 value1 = (value1 == value2) ? 0 : ((value1 <
  1034.                     value2) ? -1 : 1);
  1035.             }
  1036.             else
  1037.                 value1 = my_stricmp(result1, result2);
  1038.             if (value1)
  1039.             {
  1040.                 value2 = (value1 > 0) ? 1 : 0;
  1041.                 if (op == '<')
  1042.                     value2 = 1 - value2;
  1043.             }
  1044.             else
  1045.                 value2 = value3;
  1046.             new_free(&result2);
  1047.             sprintf(tmp, "%ld", value2);
  1048.             malloc_strcpy(&result1, tmp);
  1049.             return result1;
  1050.         case '~':
  1051.             if (ptr == str)
  1052.             {
  1053.                 if (stage != NU_BITW)
  1054.                     break;
  1055.                 result1 = next_unit(str+1, args, arg_flag,
  1056.                     stage);
  1057.                 if (isdigit(*result1))
  1058.                 {
  1059.                     value1 = atol(result1);
  1060.                     value2 = ~value1;
  1061.                 }
  1062.                 else
  1063.                     value2 = 0;
  1064.                 sprintf(tmp, "%ld", value2);
  1065.                 malloc_strcpy(&result1, tmp);
  1066.                 return result1;
  1067.             }
  1068.                         else
  1069.                         {
  1070.                                 ptr = lastop(ptr);
  1071.                                 break;
  1072.                         }
  1073.         case '!':
  1074.             if (ptr == str)
  1075.             {
  1076.                 if (stage != NU_UNIT)
  1077.                     break;
  1078.                 result1 = next_unit(str+1, args, arg_flag,
  1079.                     stage);
  1080.                 if (isdigit(*result1))
  1081.                 {
  1082.                     value1 = atol(result1);
  1083.                     value2 = value1 ? 0 : 1;
  1084.                 }
  1085.                 else
  1086.                 {
  1087.                     value2 = ((*result1)?0:1);
  1088.                 }
  1089.                 sprintf(tmp, "%ld", value2);
  1090.                 malloc_strcpy(&result1, tmp);
  1091.                 return result1;
  1092.             }
  1093.             if (stage != NU_COMP || ptr[1] != '=')
  1094.             {
  1095.                 ptr = lastop(ptr);
  1096.                 break;
  1097.             }
  1098.             *ptr = '\0';
  1099.             ptr += 2;
  1100.             result1 = next_unit(str, args, arg_flag, stage);
  1101.             result2 = next_unit(ptr, args, arg_flag, stage);
  1102.             if (!my_stricmp(result1, result2))
  1103.                 malloc_strcpy(&result1, "0");
  1104.             else
  1105.                 malloc_strcpy(&result1, "1");
  1106.             new_free(&result2);
  1107.             return result1;
  1108.                 case ',': 
  1109.             /*
  1110.              * this utterly kludge code is needed (?) to get
  1111.              * around bugs introduced from hop's patches to
  1112.              * alias.c.  the $, variable stopped working
  1113.              * because of this.  -mrg, july 94.
  1114.              */
  1115.             if (ptr == str || (ptr > str && ptr[-1] == '$'))
  1116.                 break;
  1117.                         if (stage != NU_EXPR)
  1118.                         {
  1119.                 ptr = lastop(ptr);
  1120.                 break;
  1121.             }
  1122.             *ptr++ = '\0';
  1123.             result1 = next_unit(str, args, arg_flag, stage);
  1124.             result2 = next_unit(ptr, args, arg_flag, stage);
  1125.             new_free(&result1);
  1126.             return result2;
  1127.         }
  1128.     }
  1129.     if (stage != NU_UNIT)
  1130.         return next_unit(str, args, arg_flag, stage+1);
  1131.     if (isdigit(*str) || *str == '+' || *str == '-')
  1132.         malloc_strcpy(&result1, str);
  1133.     else
  1134.     {
  1135.         if (*str == '#' || *str=='@')
  1136.             op = *str++;
  1137.         else
  1138.             op = '\0';
  1139.         result1 = find_inline(str);
  1140.         if (!result1)
  1141.             malloc_strcpy(&result1, empty_string);
  1142.         if (op)
  1143.         {
  1144.             if (op == '#')
  1145.                 value1 = word_count(result1);
  1146.             else if (op == '@')
  1147.                 value1 = strlen(result1);
  1148.             sprintf(tmp, "%ld", value1);
  1149.             malloc_strcpy(&result1, tmp);
  1150.         }
  1151.     }
  1152.     return result1;
  1153. }
  1154.  
  1155. /*
  1156.  * parse_inline:  This evaluates user-variable expression.  I'll talk more
  1157.  * about this at some future date. The ^ function and some fixes by
  1158.  * troy@cbme.unsw.EDU.AU (Troy Rollo) 
  1159.  */
  1160. char    *
  1161. parse_inline(str, args, args_flag)
  1162.     char    *str;
  1163.     char    *args;
  1164.     int    *args_flag;
  1165. {
  1166.     return next_unit(str, args, args_flag, NU_EXPR);
  1167. }
  1168.  
  1169. /*
  1170.  * arg_number: Returns the argument 'num' from 'str', or, if 'num' is
  1171.  * negative, returns from argument 'num' to the end of 'str'.  You might be
  1172.  * wondering what's going on down there... here goes.  First we copy 'str' to
  1173.  * malloced space.  Then, using next_arg(), we strip out each argument ,
  1174.  * putting them in arg_list, and putting their position in the original
  1175.  * string in arg_list_pos.  Anyway, once parsing is done, the arguments are
  1176.  * returned directly from the arg_list array... or in the case of negative
  1177.  * 'num', the arg_list_pos is used to return the postion of the rest of the
  1178.  * args in the original string... got it?  Anyway, the bad points of the
  1179.  * routine:  1) Always parses out everything, even if only one arg is used.
  1180.  * 2) The malloced stuff remains around until arg_number is called with a
  1181.  * different string. Even then, some malloced stuff remains around.  This can
  1182.  * be fixed. 
  1183.  */
  1184.  
  1185. #define    LAST_ARG 8000
  1186.  
  1187. extern    char    *arg_number(lower_lim, upper_lim, str)
  1188. int    lower_lim,
  1189.     upper_lim;
  1190. char    *str;
  1191. {
  1192.     char    *ptr,
  1193.         *arg,
  1194.         c;
  1195.     int    use_full = 0;
  1196.     unsigned int    pos,
  1197.         start_pos;
  1198.     static    char    *last_args = (char *) 0;
  1199.     static    char    *last_range = (char *) 0;
  1200.     static    char    **arg_list = (char **) 0;
  1201.     static    unsigned int    *arg_list_pos = (unsigned int *) 0;
  1202.     static    unsigned int    *arg_list_end_pos = (unsigned int *) 0;
  1203.     static    int    arg_list_size;
  1204.  
  1205.     if (eval_args)
  1206.     {
  1207.         int    arg_list_limit;
  1208.  
  1209.         eval_args = 0;
  1210.         new_free(&arg_list);
  1211.         new_free(&arg_list_pos);
  1212.         new_free(&arg_list_end_pos);
  1213.         arg_list_size = 0;
  1214.         arg_list_limit = 10;
  1215.         arg_list = (char **) new_malloc(sizeof(char *) *
  1216.             arg_list_limit);
  1217.         arg_list_pos = (unsigned int *) new_malloc(sizeof(unsigned int)
  1218.             * arg_list_limit);
  1219.         arg_list_end_pos = (unsigned int *) new_malloc(sizeof(unsigned
  1220.             int) * arg_list_limit);
  1221.         malloc_strcpy(&last_args, str);
  1222.         ptr = last_args;
  1223.         pos = 0;
  1224.         while ((arg = alias_arg(&ptr, &start_pos)) != NULL)
  1225.         {
  1226.             arg_list_pos[arg_list_size] = pos;
  1227.             pos += start_pos + strlen(arg);
  1228.             arg_list_end_pos[arg_list_size] = pos++;
  1229.             arg_list[arg_list_size++] = arg;
  1230.             if (arg_list_size == arg_list_limit)
  1231.             {
  1232.                 arg_list_limit += 10;
  1233.                 arg_list = (char **) new_realloc(arg_list,
  1234.                     sizeof(char *) * arg_list_limit);
  1235.                 arg_list_pos = (unsigned int *)
  1236.                     new_realloc(arg_list_pos,
  1237.                     sizeof(unsigned int) * arg_list_limit);
  1238.                 arg_list_end_pos = (unsigned int *)
  1239.                     new_realloc(arg_list_end_pos,
  1240.                     sizeof(unsigned int) *
  1241.                     arg_list_limit);
  1242.             }
  1243.         }
  1244.     }
  1245.     if (upper_lim == LAST_ARG && lower_lim == LAST_ARG)
  1246.         upper_lim = lower_lim = arg_list_size - 1;
  1247.     if (arg_list_size == 0)
  1248.         return (empty_string);
  1249.     if ((upper_lim >= arg_list_size) || (upper_lim < 0))
  1250.     {
  1251.         use_full = 1;
  1252.         upper_lim = arg_list_size - 1;
  1253.     }
  1254.     if (upper_lim < lower_lim)
  1255.                 return empty_string;
  1256.     if (lower_lim >= arg_list_size)
  1257.         lower_lim = arg_list_size - 1;
  1258.     else if (lower_lim < 0)
  1259.         lower_lim = 0;
  1260.     if ((use_full == 0) && (lower_lim == upper_lim))
  1261.         return (arg_list[lower_lim]);
  1262.     c = *(str + arg_list_end_pos[upper_lim]);
  1263.     *(str + arg_list_end_pos[upper_lim]) = (char) 0;
  1264.     malloc_strcpy(&last_range, str + arg_list_pos[lower_lim]);
  1265.     *(str + arg_list_end_pos[upper_lim]) = c;
  1266.     return (last_range);
  1267. }
  1268.  
  1269. /*
  1270.  * parse_number: returns the next number found in a string and moves the
  1271.  * string pointer beyond that point    in the string.  Here's some examples: 
  1272.  *
  1273.  * "123harhar"  returns 123 and str as "harhar" 
  1274.  *
  1275.  * while: 
  1276.  *
  1277.  * "hoohar"     returns -1  and str as "hoohar" 
  1278.  */
  1279. extern    int    
  1280. parse_number(str)
  1281.     char    **str;
  1282. {
  1283.     int    ret;
  1284.     char    *ptr;
  1285.  
  1286.     ptr = *str;
  1287.     if (isdigit(*ptr))
  1288.     {
  1289.         ret = atoi(ptr);
  1290.         for (; isdigit(*ptr); ptr++);
  1291.         *str = ptr;
  1292.     }
  1293.     else
  1294.         ret = -1;
  1295.     return (ret);
  1296. }
  1297.  
  1298. void    
  1299. do_alias_string()
  1300. {
  1301.     malloc_strcpy(&alias_string, get_input());
  1302.     irc_io_loop = 0;
  1303. }
  1304.  
  1305. /*
  1306.  * expander_addition: This handles string width formatting for irc variables
  1307.  * when [] is specified.  
  1308.  */
  1309. static    void    
  1310. expander_addition(buff, add, length, quote_em)
  1311.     char    *buff,
  1312.         *add;
  1313.     int    length;
  1314.     char    *quote_em;
  1315. {
  1316.     char    format[40],
  1317.         *ptr;
  1318.  
  1319.     if (length)
  1320.     {
  1321.         sprintf(format, "%%%d.%ds", -length, (length < 0 ? -length :
  1322.             length));
  1323.         sprintf(buffer, format, add);
  1324.         add = buffer;
  1325.     }
  1326.     if (quote_em)
  1327.     {
  1328.         ptr = double_quote(add, quote_em);
  1329.         strmcat(buff, ptr, BIG_BUFFER_SIZE);
  1330.         new_free(&ptr);
  1331.     }
  1332.     else
  1333.                 if (buff)
  1334.                 strmcat(buff, add, BIG_BUFFER_SIZE);
  1335. }
  1336.  
  1337. /* MatchingBracket returns the next unescaped bracket of the given type */
  1338. char    *
  1339. MatchingBracket(string, left, right)
  1340.     char    *string;
  1341.     char    left,
  1342.         right;
  1343. {
  1344.     int    bracket_count = 1;
  1345.  
  1346.     while (*string && bracket_count)
  1347.     {
  1348.         if (*string == left)
  1349.             bracket_count++;
  1350.         else if (*string == right)
  1351.         {
  1352.             if (!--bracket_count)
  1353.                 return string;
  1354.         }
  1355.         else if (*string == '\\' && string[1])
  1356.             string++;
  1357.         string++;
  1358.     }
  1359.     return (char *) 0;
  1360. }
  1361.  
  1362.  
  1363. /*
  1364.  * alias_special_char: Here we determin what to do with the character after
  1365.  * the $ in a line of text. The special characters are described more fulling
  1366.  * in the help/ALIAS file.  But they are all handled here. Paremeters are the
  1367.  * name of the alias (if applicable) to prevent deadly recursion, a
  1368.  * destination buffer (of size BIG_BUFFER_SIZE) to which things are appended,
  1369.  * a ptr to the string (the first character of which is the special
  1370.  * character, the args to the alias, and a character indication what
  1371.  * characters in the string should be quoted with a backslash.  It returns a
  1372.  * pointer to the character right after the converted alias.
  1373.  
  1374.  The args_flag is set to 1 if any of the $n, $n-, $n-m, $-m, $*, or $() is used
  1375.  in the alias.  Otherwise it is left unchanged.
  1376.  */
  1377. /*ARGSUSED*/
  1378. static    char    *
  1379. alias_special_char(name, buffer, ptr, args, quote_em,args_flag)
  1380.     char    *name;
  1381.     char    *buffer;
  1382.     char    *ptr;
  1383.     char    *args;
  1384.     char    *quote_em;
  1385.     int    *args_flag;
  1386. {
  1387.     char    *tmp,
  1388.         c;
  1389.     int    upper,
  1390.     lower,
  1391.     length;
  1392.  
  1393.     length = 0;
  1394.     if ((c = *ptr) == LEFT_BRACKET)
  1395.     {
  1396.         ptr++;
  1397.         if ((tmp = (char *) index(ptr, RIGHT_BRACKET)) != NULL)
  1398.         {
  1399.             *(tmp++) = (char) 0;
  1400.             length = atoi(ptr);
  1401.             ptr = tmp;
  1402.             c = *ptr;
  1403.         }
  1404.         else
  1405.         {
  1406.             say("Missing %c", RIGHT_BRACKET);
  1407.             return (ptr);
  1408.         }
  1409.     }
  1410.     tmp = ptr+1;
  1411.     switch (c)
  1412.     {
  1413.     case LEFT_PAREN:
  1414.         {
  1415.             define_big_buffer(sub_buffer);
  1416.  
  1417.             if ((ptr = MatchingBracket(tmp, LEFT_PAREN,
  1418.                 RIGHT_PAREN)) || (ptr = (char *) index(tmp,
  1419.                 RIGHT_PAREN)))
  1420.                 *(ptr++) = (char) 0;
  1421.             tmp = expand_alias((char *) 0, tmp, args, args_flag,
  1422.                 NULL);
  1423.             *sub_buffer = (char) 0;
  1424.             alias_special_char((char *) 0, sub_buffer, tmp,
  1425.                 args, quote_em,args_flag);
  1426.             expander_addition(buffer, sub_buffer, length, quote_em);
  1427.             new_free(&tmp);
  1428.             *args_flag = 1;
  1429.             free_big_buffer(sub_buffer);
  1430.         }
  1431.         return (ptr);
  1432.     case '!':
  1433.         if ((ptr = (char *) index(tmp, '!')) != NULL)
  1434.             *(ptr++) = (char) 0;
  1435.         if ((tmp = do_history(tmp, empty_string)) != NULL)
  1436.         {
  1437.             expander_addition(buffer, tmp, length, quote_em);
  1438.             new_free(&tmp);
  1439.         }
  1440.         return (ptr);
  1441.     case LEFT_BRACE:
  1442.         if ((ptr = (char *) index(tmp, RIGHT_BRACE)) != NULL)
  1443.             *(ptr++) = (char) 0;
  1444.         if ((tmp = parse_inline(tmp, args, args_flag)) != NULL)
  1445.         {
  1446.             expander_addition(buffer, tmp, length, quote_em);
  1447.             new_free(&tmp);
  1448.         }
  1449.         return (ptr);
  1450.     case DOUBLE_QUOTE:
  1451.         if ((ptr = (char *) index(tmp, DOUBLE_QUOTE)) != NULL)
  1452.             *(ptr++) = (char) 0;
  1453.         alias_string = (char *) 0;
  1454.         if (irc_io(tmp, do_alias_string, use_input, 1))
  1455.         {
  1456.             yell("Illegal recursive edit");
  1457.             break;
  1458.         }
  1459.         expander_addition(buffer, alias_string, length, quote_em);
  1460.         new_free(&alias_string);
  1461.         return (ptr);
  1462.     case '*':
  1463.         expander_addition(buffer, args, length, quote_em);
  1464.         *args_flag = 1;
  1465.         return (ptr + 1);
  1466.     default:
  1467.         if (isdigit(c) || (c == '-') || c == '~')
  1468.         {
  1469.             *args_flag = 1;
  1470.             if (*ptr == '~')
  1471.             {
  1472.                 lower = upper = LAST_ARG;
  1473.                 ptr++;
  1474.             }
  1475.             else
  1476.             {
  1477.                 lower = parse_number(&ptr);
  1478.                 if (*ptr == '-')
  1479.                 {
  1480.                     ptr++;
  1481.                     upper = parse_number(&ptr);
  1482.                 }
  1483.                 else
  1484.                     upper = lower;
  1485.             }
  1486.             expander_addition(buffer, arg_number(lower, upper,
  1487.                 args), length, quote_em);
  1488.             return (ptr ? ptr : empty_string);
  1489.         }
  1490.         else
  1491.         {
  1492.             char    *rest,
  1493.                 c = (char) 0;
  1494.  
  1495.         /*
  1496.          * Why use ptr+1?  Cause try to maintain backward compatability
  1497.          * can be a pain in the butt.  Basically, we don't want any of
  1498.          * the illegal characters in the alias, except that things like
  1499.          * $* and $, were around first, so they must remain legal.  So
  1500.          * we skip the first char after the $.  Does this make sense?
  1501.          */
  1502.             /* special case for $ */
  1503.             if (*ptr == '$')
  1504.             {
  1505.                 rest = ptr+1;
  1506.                 c = *rest;
  1507.                 *rest = (char) 0;
  1508.             }
  1509.             else if ((rest = sindex(ptr+1, alias_illegals)) != NULL)
  1510.             {
  1511.                 if (isalpha(*ptr) || *ptr == '_')
  1512.                     while ((*rest == LEFT_BRACKET ||
  1513.                         *rest == LEFT_PAREN) &&
  1514.                         (tmp = MatchingBracket(rest+1,
  1515.                         *rest, (*rest == LEFT_BRACKET) ?
  1516.                         RIGHT_BRACKET: RIGHT_PAREN)))
  1517.                         rest = tmp + 1;
  1518.                 c = *rest;
  1519.                 *rest = (char) 0;
  1520.             }
  1521.             if ((tmp = parse_inline(ptr, args, args_flag)) != NULL)
  1522.             {
  1523.                 expander_addition(buffer, tmp, length,
  1524.                     quote_em);
  1525.                 new_free(&tmp);
  1526.             }
  1527.             if (rest)
  1528.                 *rest = c;
  1529.             return(rest);
  1530.         }
  1531.     }
  1532.     return NULL;
  1533. }
  1534.  
  1535.  
  1536. /*
  1537.  * expand_alias: Expands inline variables in the given string and returns the
  1538.  * expanded string in a new string which is malloced by expand_alias(). 
  1539.  *
  1540.  * Also unescapes anything that was quoted with a backslash
  1541.  *
  1542.  * Behaviour is modified by the following:
  1543.  *    Anything between brackets (...) {...} is left unmodified.
  1544.  *    If more_text is supplied, the text is broken up at
  1545.  *        semi-colons and returned one at a time. The unprocessed
  1546.  *        portion is written back into more_text.
  1547.  *    Backslash escapes are unescaped.
  1548.  */
  1549.  
  1550. char    *
  1551. expand_alias(name, string, args,args_flag, more_text)
  1552.     char    *name,
  1553.         *string,
  1554.         *args;
  1555.     int    *args_flag;
  1556.     char    **more_text;
  1557. {
  1558.     define_big_buffer(buffer);
  1559.     char    *ptr,
  1560.         *stuff = (char *) 0,
  1561.         *free_stuff;
  1562.     char    *quote_em,
  1563.         *quote_str = (char *) 0;
  1564.     char    ch;
  1565.     int    quote_cnt = 0;
  1566.     int    is_quote = 0;
  1567.     void    (*str_cat)();
  1568.  
  1569.     if (*string == '@' && more_text)
  1570.     {
  1571.         str_cat = strmcat;
  1572.         *args_flag = 1; /* Stop the @ command from auto appending */
  1573.     }
  1574.     else
  1575.         str_cat = strmcat_ue;
  1576.     malloc_strcpy(&stuff, string);
  1577.     free_stuff = stuff;
  1578.     *buffer = (char) 0;
  1579.     eval_args = 1;
  1580.     ptr = stuff;
  1581.     if (more_text)
  1582.         *more_text = NULL;
  1583.     while (ptr && *ptr)
  1584.     {
  1585.         if (is_quote)
  1586.         {
  1587.             is_quote = 0;
  1588.             ++ptr;
  1589.             continue;
  1590.         }
  1591.         switch(*ptr)
  1592.         {
  1593.         case '$':
  1594.     /*
  1595.      * The test here ensures that if we are in the expression
  1596.      * evaluation command, we don't expand $. In this case we
  1597.      * are only coming here to do command separation at ';'s.
  1598.      * If more_text is not defined, and the first character is
  1599.      * '@', we have come here from [] in an expression.
  1600.      */
  1601.             if (more_text && *string == '@')
  1602.             {
  1603.                 ptr++;
  1604.                 break;
  1605.             }
  1606.             *(ptr++) = (char) 0;
  1607.             (*str_cat)(buffer, stuff, BIG_BUFFER_SIZE);
  1608.             while (*ptr == '^')
  1609.             {
  1610.                 ptr++;
  1611.                 if (quote_str)
  1612.                     quote_str = (char *)
  1613.                         new_realloc(quote_str,
  1614.                         sizeof(char) * (quote_cnt + 2));
  1615.                 else
  1616.                     quote_str = (char *)
  1617.                         new_malloc(sizeof(char) *
  1618.                         (quote_cnt + 2));
  1619.                 quote_str[quote_cnt++] = *(ptr++);
  1620.                 quote_str[quote_cnt] = (char) 0;
  1621.             }
  1622.             quote_em = quote_str;
  1623.             stuff = alias_special_char(name, buffer, ptr, args,
  1624.                 quote_em, args_flag);
  1625.             if (stuff)
  1626.                 new_free("e_str);
  1627.             quote_cnt = 0;
  1628.             ptr = stuff;
  1629.             break;
  1630.         case ';':
  1631.             if (!more_text)
  1632.             {
  1633.                 ptr++;
  1634.                 break;
  1635.             }
  1636.             *more_text = string + (ptr - free_stuff) +1;
  1637.             *ptr = '\0'; /* To terminate the loop */
  1638.             break;
  1639.         case LEFT_PAREN:
  1640.         case LEFT_BRACE:
  1641.             ch = *ptr;
  1642.             *ptr = '\0';
  1643.             (*str_cat)(buffer, stuff, BIG_BUFFER_SIZE);
  1644.             stuff = ptr;
  1645.             *args_flag = 1;
  1646.             if (!(ptr = MatchingBracket(stuff + 1, ch,
  1647.                     (ch == LEFT_PAREN) ?
  1648.                     RIGHT_PAREN : RIGHT_BRACE)))
  1649.             {
  1650.                 yell("Unmatched %c", ch);
  1651.                 ptr = stuff + strlen(stuff+1)+1;
  1652.             }
  1653.             else
  1654.                 ptr++;
  1655.             *stuff = ch;
  1656.             ch = *ptr;
  1657.             *ptr = '\0';
  1658.             strmcat(buffer, stuff, BIG_BUFFER_SIZE);
  1659.             stuff = ptr;
  1660.             *ptr = ch;
  1661.             break;
  1662.         case '\\':
  1663.             is_quote = 1;
  1664.             ptr++;
  1665.             break;
  1666.         default:
  1667.             ptr++;
  1668.             break;
  1669.         }
  1670.     }
  1671.     if (stuff)
  1672.         (*str_cat)(buffer, stuff, BIG_BUFFER_SIZE);
  1673.     ptr = (char *) 0;
  1674.     new_free(&free_stuff);
  1675.     malloc_strcpy(&ptr, buffer);
  1676.     if (get_int_var(DEBUG_VAR) & DEBUG_EXPANSIONS)
  1677.         yell("Expanded [%s] to [%s]",
  1678.             string, ptr);
  1679.     free_big_buffer(buffer);
  1680.     return (ptr);
  1681. }
  1682.  
  1683. /*
  1684.  * get_alias: returns the alias matching 'name' as the function value. 'args'
  1685.  * are expanded as needed, etc.  If no matching alias is found, null is
  1686.  * returned, cnt is 0, and full_name is null.  If one matching alias is
  1687.  * found, it is retuned, with cnt set to 1 and full_name set to the full name
  1688.  * of the alias.  If more than 1 match are found, null is returned, cnt is
  1689.  * set to the number of matches, and fullname is null. NOTE: get_alias()
  1690.  * mallocs the space for the full_name, but returns the actual value of the
  1691.  * alias if found! 
  1692.  */
  1693. char    *
  1694. get_alias(type, name, cnt, full_name)
  1695.     int    type;
  1696.     char    *name,
  1697.         **full_name;
  1698.     int    *cnt;
  1699. {
  1700.     Alias    *tmp;
  1701.  
  1702.     *full_name = (char *) 0;
  1703.     if ((name == (char *) 0) || (*name == (char) 0))
  1704.     {
  1705.         *cnt = 0;
  1706.         return ((char *) 0);
  1707.     }
  1708.     if ((tmp = find_alias(&(alias_list[type]), name, 0, cnt)) != NULL)
  1709.     {
  1710.         if (*cnt < 2)
  1711.         {
  1712.             malloc_strcpy(full_name, tmp->name);
  1713.             return (tmp->stuff);
  1714.         }
  1715.     }
  1716.     return ((char *) 0);
  1717. }
  1718.  
  1719. /*
  1720.  * match_alias: this returns a list of alias names that match the given name.
  1721.  * This is used for command completion etc.  Note that the returned array is
  1722.  * malloced in this routine.  Returns null if no matches are found 
  1723.  */
  1724. char    **
  1725. match_alias(name, cnt, type)
  1726.     char    *name;
  1727.     int    *cnt;
  1728.     int    type;
  1729. {
  1730.     Alias    *tmp;
  1731.     char    **matches = (char **) 0;
  1732.     int    matches_size = 5;
  1733.     int    len;
  1734.     char    *last_match = (char *) 0;
  1735.     char    *dot;
  1736.  
  1737.     len = strlen(name);
  1738.     *cnt = 0;
  1739.     matches = (char    **) new_malloc(sizeof(char *) * matches_size);
  1740.     for (tmp = alias_list[type]; tmp; tmp = tmp->next)
  1741.     {
  1742.         if (strncmp(name, tmp->name, len) == 0)
  1743.         {
  1744.             if ((dot = (char *) index(tmp->name+len, '.')) != NULL)
  1745.             {
  1746.                 if (type == COMMAND_ALIAS)
  1747.                     continue;
  1748.                 else
  1749.                 {
  1750.                     *dot = '\0';
  1751.                     if (last_match && !strcmp(last_match,
  1752.                             tmp->name))
  1753.                     {
  1754.                         *dot = '.';
  1755.                         continue;
  1756.                     }
  1757.                 }
  1758.             }
  1759.             matches[*cnt] = (char *) 0;
  1760.             malloc_strcpy(&(matches[*cnt]), tmp->name);
  1761.             last_match = matches[*cnt];
  1762.             if (dot)
  1763.                 *dot = '.';
  1764.             if (++(*cnt) == matches_size)
  1765.             {
  1766.                 matches_size += 5;
  1767.                 matches = (char    **) new_realloc(matches,
  1768.                     sizeof(char *) * matches_size);
  1769.             }
  1770.         }
  1771.         else if (*cnt)
  1772.             break;
  1773.     }
  1774.     if (*cnt)
  1775.     {
  1776.         matches = (char    **) new_realloc(matches, sizeof(char *) *
  1777.             (*cnt + 1));
  1778.         matches[*cnt] = (char *) 0;
  1779.     }
  1780.     else
  1781.         new_free(&matches);
  1782.     return (matches);
  1783. }
  1784.  
  1785. /* delete_alias: The alias name is removed from the alias list. */
  1786. void
  1787. delete_alias(type, name)
  1788.     int    type;
  1789.     char    *name;
  1790. {
  1791.     Alias    *tmp;
  1792.  
  1793.     upper(name);
  1794.     if ((tmp = find_alias(&(alias_list[type]), name, 1, (int *) NULL))
  1795.             != NULL)
  1796.     {
  1797.         new_free(&(tmp->name));
  1798.         new_free(&(tmp->stuff));
  1799.         new_free(&tmp);
  1800.         if (type == COMMAND_ALIAS)
  1801.             say("Alias    %s removed", name);
  1802.         else
  1803.             say("Assign %s removed", name);
  1804.     }
  1805.     else
  1806.         say("No such alias: %s", name);
  1807. }
  1808.  
  1809. /*
  1810.  * list_aliases: Lists all aliases matching 'name'.  If name is null, all
  1811.  * aliases are listed 
  1812.  */
  1813. void
  1814. list_aliases(type, name)
  1815.     int    type;
  1816.     char    *name;
  1817. {
  1818.     Alias    *tmp;
  1819.     int    len;
  1820.     int    DotLoc,
  1821.         LastDotLoc = 0;
  1822.     char    *LastStructName = NULL;
  1823.     char    *s;
  1824.  
  1825.     if (type == COMMAND_ALIAS)
  1826.         say("Aliases:");
  1827.     else
  1828.         say("Assigns:");
  1829.     if (name)
  1830.     {
  1831.         upper(name);
  1832.         len = strlen(name);
  1833.     }
  1834.     else
  1835.         len = 0;
  1836.     for (tmp = alias_list[type]; tmp; tmp = tmp->next)
  1837.  
  1838.     {
  1839.         if (!name || !strncmp(tmp->name, name, len))
  1840.         {
  1841.             s = index(tmp->name + len, '.');
  1842.             if (!s)
  1843.                 say("\t%s\t%s", tmp->name, tmp->stuff);
  1844.             else
  1845.             {
  1846.                 DotLoc = s - tmp->name;
  1847.                 if (!LastStructName || (DotLoc != LastDotLoc) || strncmp(tmp->name, LastStructName, DotLoc))
  1848.                 {
  1849.                     say("\t%*.*s\t<Structure>", DotLoc, DotLoc, tmp->name);
  1850.                     LastStructName = tmp->name;
  1851.                     LastDotLoc = DotLoc;
  1852.                 }
  1853.             }
  1854.         }
  1855.     }
  1856. }
  1857.  
  1858. /*
  1859.  * mark_alias: sets the mark field of the given alias to 'flag', and returns
  1860.  * the previous value of the mark.  If the name is not found, -1 is returned.
  1861.  * This is used to prevent recursive aliases by marking and unmarking
  1862.  * aliases, and not reusing an alias that has previously been marked.  I'll
  1863.  * explain later 
  1864.  */
  1865. int
  1866. mark_alias(name, flag)
  1867.     char    *name;
  1868.     int    flag;
  1869. {
  1870.     int    old_mark;
  1871.     Alias    *tmp;
  1872.     int    match;
  1873.  
  1874.     if ((tmp = find_alias(&(alias_list[COMMAND_ALIAS]), name, 0, &match))
  1875.             != NULL)
  1876.     {
  1877.         if (match < 2)
  1878.         {
  1879.             old_mark = tmp->mark;
  1880.         /* New handling of recursion */
  1881.             if (flag)
  1882.             {
  1883.                 int    i;
  1884.                 /* Count recursion */
  1885.  
  1886.                 tmp->mark = tmp->mark + flag;
  1887.                 if ((i = get_int_var(MAX_RECURSIONS_VAR)) > 1)
  1888.                 {
  1889.                     if (tmp->mark > i)
  1890.                     {
  1891.                         tmp->mark = 0;
  1892.                         return(1); /* MAX exceeded. */
  1893.                     }
  1894.                     else return(0);
  1895.                 /* In recursion but it's ok */
  1896.                 }
  1897.                 else
  1898.                 {
  1899.                     if (tmp->mark > 1)
  1900.                     {
  1901.                         tmp->mark = 0;
  1902.                         return(1);
  1903.                 /* max of 1 here.. exceeded */
  1904.                     }
  1905.                     else return(0);
  1906.                 /* In recursion but it's ok */
  1907.                 }
  1908.             }
  1909.             else
  1910.         /* Not in recursion at all */
  1911.             {
  1912.                 tmp->mark = 0;
  1913.                 return(old_mark);
  1914.             /* This one gets ignored anyway */
  1915.             }
  1916.         }
  1917.     }
  1918.     return (-1);
  1919. }
  1920.  
  1921. /*
  1922.  * execute_alias: After an alias has been identified and expanded, it is sent
  1923.  * here for proper execution.  This routine mainly prevents recursive
  1924.  * aliasing.  The name is the full name of the alias, and the alias is
  1925.  * already expanded alias (both of these parameters are returned by
  1926.  * get_alias()) 
  1927.  */
  1928. void
  1929. execute_alias(alias_name, alias, args)
  1930.     char    *alias_name,
  1931.         *alias,
  1932.         *args;
  1933. {
  1934.     if (mark_alias(alias_name, 1))
  1935.         say("Maximum recursion count exceeded in: %s", alias_name);
  1936.     else
  1937.     {
  1938.         parse_line(alias_name, alias, args, 0,1);
  1939.         mark_alias(alias_name, 0);
  1940.     }
  1941. }
  1942.  
  1943. /*
  1944.  * save_aliases: This will write all of the aliases to the FILE pointer fp in
  1945.  * such a way that they can be read back in using LOAD or the -l switch 
  1946.  */
  1947. void
  1948. save_aliases(fp, do_all)
  1949.     FILE    *fp;
  1950.     int    do_all;
  1951. {
  1952.     Alias    *tmp;
  1953.  
  1954.     for (tmp = alias_list[VAR_ALIAS]; tmp; tmp = tmp->next)
  1955.         if (!tmp->global || do_all)
  1956.             fprintf(fp, "ASSIGN %s %s\n", tmp->name, tmp->stuff);
  1957.     for (tmp = alias_list[COMMAND_ALIAS]; tmp; tmp = tmp->next)
  1958.         if (!tmp->global || do_all)
  1959.             fprintf(fp, "ALIAS %s %s\n", tmp->name, tmp->stuff);
  1960. }
  1961.  
  1962. /* The Built-In Alias expando functions */
  1963. static    char    *
  1964. alias_line()
  1965. {
  1966.     return(get_input());
  1967. }
  1968.  
  1969. static    char    *
  1970. alias_buffer()
  1971. {
  1972.     return cut_buffer;
  1973. }
  1974.  
  1975. static    char    *
  1976. alias_time()
  1977. {
  1978.     return(update_clock(GET_TIME));
  1979. }
  1980.  
  1981. static    char    *
  1982. alias_dollar()
  1983. {
  1984.     return("$");
  1985. }
  1986.  
  1987. static    char    *
  1988. alias_detected()
  1989. {
  1990.     return last_notify_nick;
  1991. }
  1992.  
  1993. static    char    *
  1994. alias_nick()
  1995. {
  1996.     return(get_server_nickname(curr_scr_win->server));
  1997. }
  1998.  
  1999. static    char    *
  2000. alias_away()
  2001. {
  2002.     return server_list[curr_scr_win->server].away;
  2003. }
  2004.  
  2005. static    char    *
  2006. alias_sent_nick()
  2007. {
  2008.     return (sent_nick) ? sent_nick : empty_string;
  2009. }
  2010.  
  2011. static    char    *
  2012. alias_recv_nick()
  2013. {
  2014.     return (recv_nick) ? recv_nick : empty_string;
  2015. }
  2016.  
  2017. static    char    *
  2018. alias_msg_body()
  2019. {
  2020.     return (sent_body) ? sent_body : empty_string;
  2021. }
  2022.  
  2023. static    char    *
  2024. alias_joined_nick()
  2025. {
  2026.     return (joined_nick) ? joined_nick : empty_string;
  2027. }
  2028.  
  2029. static    char    *
  2030. alias_public_nick()
  2031. {
  2032.     return (public_nick) ? public_nick : empty_string;
  2033. }
  2034.  
  2035. static    char    *
  2036. alias_channel()
  2037. {
  2038.     char    *tmp;
  2039.  
  2040.     return (tmp = get_channel_by_refnum(0)) ? tmp : "0";
  2041. }
  2042.  
  2043. static    char    *
  2044. alias_server()
  2045. {
  2046.     return (parsing_server_index == -1) ?
  2047.         get_server_itsname(parsing_server_index) :
  2048.         (get_window_server(0) != -1) ?
  2049.             get_server_itsname(get_window_server(0)) : empty_string;
  2050. }
  2051.  
  2052. static    char    *
  2053. alias_query_nick()
  2054. {
  2055.     char    *tmp;
  2056.  
  2057.     return (tmp = query_nick()) ? tmp : empty_string;
  2058. }
  2059.  
  2060. static    char    *
  2061. alias_target()
  2062. {
  2063.     char    *tmp;
  2064.  
  2065.     return (tmp = get_target_by_refnum(0)) ? tmp : empty_string;
  2066. }
  2067.  
  2068. static    char    *
  2069. alias_invite()
  2070. {
  2071.     return (invite_channel) ? invite_channel : empty_string;
  2072. }
  2073.  
  2074. static    char    *
  2075. alias_cmdchar()
  2076. {
  2077.     static    char    thing[2];
  2078.     char    *cmdchars;
  2079.  
  2080.     if ((cmdchars = get_string_var(CMDCHARS_VAR)) == (char *) 0)
  2081.         cmdchars = DEFAULT_CMDCHARS;
  2082.     thing[0] = cmdchars[0];
  2083.     thing[1] = (char) 0;
  2084.     return(thing);
  2085. }
  2086.  
  2087. static    char    *
  2088. alias_oper()
  2089. {
  2090.     return get_server_operator(from_server) ?
  2091.         get_string_var(STATUS_OPER_VAR) : empty_string;
  2092. }
  2093.  
  2094. static    char    *
  2095. alias_chanop()
  2096. {
  2097.     char    *tmp;
  2098.  
  2099.     return ((tmp = get_channel_by_refnum(0)) && get_channel_oper(tmp,
  2100.             from_server)) ?
  2101.         "@" : empty_string;
  2102. }
  2103.  
  2104. static    char    *
  2105. alias_modes()
  2106. {
  2107.     char    *tmp;
  2108.  
  2109.     return (tmp = get_channel_by_refnum(0)) ?
  2110.         get_channel_mode(tmp, from_server) : empty_string;
  2111. }
  2112.  
  2113. /*
  2114.  * alias: the /ALIAS command.  Calls the correct alias function depending on
  2115.  * the args 
  2116.  */
  2117. void    
  2118. alias(command, args)
  2119.     char    *command,
  2120.         *args;
  2121. {
  2122.     char    *name,
  2123.         *rest;
  2124.     int    type;
  2125.     char    *ArrayIndex;
  2126.     char    *EndIndex;
  2127.  
  2128.     type = *command - 48;    /*
  2129.                  * A trick!  Yes, well, what the hell.  Note
  2130.                                  * the the command part of ALIAS is "0" and
  2131.                                  * the command part of ASSIGN is "1" in the
  2132.                  * command array list
  2133.                  */
  2134.     if ((name = next_arg(args, &rest)) != NULL)
  2135.     {
  2136.         while ((ArrayIndex = (char *) index(name, '[')) != NULL)
  2137.         {
  2138.             *ArrayIndex++ = '.';
  2139.             if ((EndIndex = MatchingBracket(ArrayIndex,
  2140.                     LEFT_BRACKET, RIGHT_BRACKET)) != NULL)
  2141.             {
  2142.                 *EndIndex++ = '\0';
  2143.                 strcat(name, EndIndex);
  2144.             }
  2145.             else
  2146.                 break;
  2147.         }
  2148.         if (*rest)
  2149.         {
  2150.             if (*rest == LEFT_BRACE)
  2151.             {
  2152.                 char    *ptr = MatchingBracket(++rest,
  2153.                         LEFT_BRACE, RIGHT_BRACE);
  2154.                 if (!ptr)
  2155.                     say("Unmatched brace in ALIAS or ASSIGN");
  2156.                 else if (ptr[1])
  2157.                 {
  2158.                     say("Junk after closing brace in ALIAS or ASSIGN");
  2159.                 }
  2160.                 else
  2161.                 {
  2162.                     *ptr = '\0';
  2163.                     add_alias(type, name, rest);
  2164.                 }
  2165.             }
  2166.             else
  2167.                 add_alias(type, name, rest);
  2168.         }
  2169.         else
  2170.         {
  2171.             if (*name == '-')
  2172.             {
  2173.                 if (*(name + 1))
  2174.                     delete_alias(type, name + 1);
  2175.                 else
  2176.                     say("You must specify an alias to be removed");
  2177.             }
  2178.             else
  2179.                 list_aliases(type, name);
  2180.         }
  2181.     }
  2182.     else
  2183.         list_aliases(type, (char *) 0);
  2184. }
  2185.  
  2186.  
  2187.  
  2188. char    *
  2189. function_left(input)
  2190.     char    *input;
  2191. {
  2192.     char    *result = (char *) 0;
  2193.     char    *count;
  2194.     int    cvalue;
  2195.  
  2196.     count = next_arg(input, &input);
  2197.     if (count)
  2198.         cvalue = atoi(count);
  2199.     else
  2200.         cvalue = 0;
  2201.     if (strlen(input) > cvalue)
  2202.         input[cvalue] = '\0';
  2203.     malloc_strcpy(&result, input);
  2204.     return result;
  2205. }
  2206.  
  2207. char    *
  2208. function_right(input)
  2209.     char    *input;
  2210. {
  2211.     char    *result = (char *) 0;
  2212.     char    *count;
  2213.     int    cvalue;
  2214.  
  2215.     count = next_arg(input, &input);
  2216.     if (count)
  2217.         cvalue = atoi(count);
  2218.     else
  2219.         cvalue = 0;
  2220.     if (strlen(input) > cvalue)
  2221.         input += strlen(input) - cvalue;
  2222.     malloc_strcpy(&result, input);
  2223.     return result;
  2224. }
  2225.  
  2226. char    *
  2227. function_mid(input)
  2228.     char    *input;
  2229. {
  2230.     char    *result = (char *) 0;
  2231.     char    *index;
  2232.     int    ivalue;
  2233.     char    *count;
  2234.     int    cvalue;
  2235.  
  2236.     index = next_arg(input, &input);
  2237.     if (index)
  2238.         ivalue = atoi(index);
  2239.     else
  2240.         ivalue = 0;
  2241.     count = next_arg(input, &input);
  2242.     if (count)
  2243.         cvalue = atoi(count);
  2244.     else
  2245.         cvalue = 0;
  2246.     if (strlen(input) > ivalue)
  2247.         input += ivalue;
  2248.     else
  2249.         *input = (char) 0;
  2250.     if (strlen(input) > cvalue)
  2251.         input[cvalue] = (char) 0;
  2252.     malloc_strcpy(&result, input);
  2253.     return result;
  2254. }
  2255.  
  2256. /* patch from Sarayan to make $rand() better */
  2257.  
  2258. #define RAND_A 16807L
  2259. #define RAND_M 2147483647L
  2260. #define RAND_Q 127773L
  2261. #define RAND_R 2836L
  2262.  
  2263. static    long    
  2264. randm(l)
  2265.     long    l;
  2266. {
  2267.     static    u_long    z = 0;
  2268.     long    t;
  2269.  
  2270. #ifndef __MSDOS__
  2271.     if (!z)
  2272.         z = (u_long) getuid();
  2273. #endif
  2274.     if (!l)
  2275.     {
  2276.         t = RAND_A * (z % RAND_Q) - RAND_R * (z / RAND_Q);
  2277.         if (t > 0)
  2278.             z = t;
  2279.         else
  2280.             z = t + RAND_M;
  2281.         return (z >> 8) | ((z & 255) << 23);
  2282.     }
  2283.     else
  2284.     {
  2285.         if (l < 0)
  2286. #ifdef __MSDOS__
  2287.             z = 0;
  2288. #else
  2289.             z = (u_long) getuid();
  2290. #endif
  2291.         else
  2292.             z = l;
  2293.         return 0;
  2294.     }
  2295. }
  2296.  
  2297. char    *
  2298. function_rand(input)
  2299.     char    *input;
  2300. {
  2301.     char    *result = (char *) 0;
  2302.     char    tmp[40];
  2303.     long    tempin;
  2304.  
  2305.     sprintf(tmp, "%ld", (tempin = atol(input)) ? randm(0L) % tempin : 0);
  2306.     malloc_strcpy(&result, tmp);
  2307.     return result;
  2308. }
  2309.  
  2310. char    *
  2311. function_srand(input)
  2312.     char    *input;
  2313. {
  2314.     char    *result = (char *) 0;
  2315.  
  2316.     if (input && *input)
  2317.         (void) randm(atol(input));
  2318.     else
  2319.         (void) randm((time_t) time(NULL));
  2320.     malloc_strcpy(&result, empty_string);
  2321.     return result;
  2322. }
  2323.  
  2324. /*ARGSUSED*/
  2325. char    *
  2326. function_time(input)
  2327.     char    *input;
  2328. {
  2329.     char    *result = (char *) 0;
  2330.     time_t    ltime;
  2331.     char    tmp[40];
  2332.  
  2333.     (void) time(<ime);
  2334.     sprintf(tmp, "%ld", ltime);
  2335.     malloc_strcpy(&result, tmp);
  2336.     return result;
  2337. }
  2338.  
  2339. char    *
  2340. function_stime(input)
  2341.     char    *input;
  2342. {
  2343.     char    *result = (char *) 0;
  2344.     time_t    ltime;
  2345.  
  2346.     ltime = atol(input);
  2347.     malloc_strcpy(&result, ctime(<ime));
  2348.     result[strlen(result) - 1] = (char) 0;
  2349.     return result;
  2350. }
  2351.  
  2352. char    *
  2353. function_tdiff(input)
  2354.     char    *input;
  2355. {
  2356.     char    *result = (char *) 0;
  2357.     time_t    ltime;
  2358.     time_t    days,
  2359.         hours,
  2360.         minutes,
  2361.         seconds;
  2362.     char    tmp[80];
  2363.     char    *tstr;
  2364.  
  2365.     ltime = atol(input);
  2366.     seconds = ltime % 60;
  2367.     ltime = (ltime - seconds) / 60;
  2368.     minutes = ltime%60;
  2369.     ltime = (ltime - minutes) / 60;
  2370.     hours = ltime % 24;
  2371.     days = (ltime - hours) / 24;
  2372.     tstr = tmp;
  2373.     if (days)
  2374.     {
  2375.         sprintf(tstr, "%d day%s ", days, (days==1)?"":"s");
  2376.         tstr += strlen(tstr);
  2377.     }
  2378.     if (hours)
  2379.     {
  2380.         sprintf(tstr, "%d hour%s ", hours, (hours==1)?"":"s");
  2381.         tstr += strlen(tstr);
  2382.     }
  2383.     if (minutes)
  2384.     {
  2385.         sprintf(tstr, "%d minute%s ", minutes, (minutes==1)?"":"s");
  2386.         tstr += strlen(tstr);
  2387.     }
  2388.     if (seconds || (!days && !hours && !minutes))
  2389.     {
  2390.         sprintf(tstr, "%d second%s", seconds, (seconds==1)?"":"s");
  2391.         tstr += strlen(tstr);
  2392.     }
  2393.     malloc_strcpy(&result, tmp);
  2394.     return result;
  2395. }
  2396.  
  2397. char    *
  2398. function_index(input)
  2399.     char    *input;
  2400. {
  2401.     char    *result = (char *) 0;
  2402.     char    *schars;
  2403.     char    *iloc;
  2404.     int    ival;
  2405.     char    tmp[40];
  2406.  
  2407.     schars = next_arg(input, &input);
  2408.     iloc = (schars) ? sindex(input, schars) : NULL;
  2409.     ival = (iloc) ? iloc - input : -1;
  2410.     sprintf(tmp, "%d", ival);
  2411.     malloc_strcpy(&result, tmp);
  2412.     return result;
  2413. }
  2414.  
  2415. char    *
  2416. function_rindex(input)
  2417.     char    *input;
  2418. {
  2419.     char    *result = (char *) 0;
  2420.     char    *schars;
  2421.     char    *iloc, *liloc;
  2422.     int    ival;
  2423.     char    tmp[40];
  2424.  
  2425.     schars = next_arg(input, &input);
  2426.     iloc = NULL;
  2427.     if (schars)
  2428.     {
  2429.         liloc = sindex(input, schars);
  2430.         while (liloc)
  2431.             liloc = sindex((iloc = liloc) + 1, schars);
  2432.     }
  2433.     ival = (iloc) ? iloc-input : -1;
  2434.     sprintf(tmp, "%d", ival);
  2435.     malloc_strcpy(&result, tmp);
  2436.     return result;
  2437. }
  2438.  
  2439. char    *
  2440. function_match(input)
  2441.     char    *input;
  2442. {
  2443.     char    *result = (char *) 0;
  2444.     char    *pattern;
  2445.     char    *word;
  2446.     int    current_match;
  2447.     int    best_match = 0;
  2448.     int    match = 0;
  2449.     int    index = 0;
  2450.     char    tmp[40];
  2451.  
  2452.     if ((pattern = next_arg(input, &input)) != NULL)
  2453.     {
  2454.         while ((word = next_arg(input, &input)) != NULL)
  2455.         {
  2456.             index++;
  2457.             if ((current_match = wild_match(pattern, word))
  2458.                     > best_match)
  2459.             {
  2460.                 match = index;
  2461.                 best_match=current_match;
  2462.             }
  2463.         }
  2464.     }
  2465.     sprintf(tmp, "%d", match);
  2466.     malloc_strcpy(&result, tmp);
  2467.     return result;
  2468. }
  2469.  
  2470. char    *
  2471. function_rmatch(input)
  2472.     char    *input;
  2473. {
  2474.     char    *result = (char *) 0;
  2475.     char    *pattern;
  2476.     char    *word;
  2477.     int    current_match;
  2478.     int    best_match = 0;
  2479.     int    match = 0;
  2480.     int    index = 0;
  2481.     char    tmp[40];
  2482.  
  2483.     if ((pattern = next_arg(input, &input)) != NULL)
  2484.     {
  2485.         while ((word = next_arg(input, &input)) != NULL)
  2486.         {
  2487.             index++;
  2488.             if ((current_match = wild_match(word, pattern)) >
  2489.                     best_match)
  2490.             {
  2491.                 match = index;
  2492.                 best_match = current_match;
  2493.             }
  2494.         }
  2495.     }
  2496.     sprintf(tmp, "%d", match);
  2497.     malloc_strcpy(&result, tmp);
  2498.     return result;
  2499. }
  2500.  
  2501. /*ARGSUSED*/
  2502. char    *
  2503. function_userhost(input)
  2504.     char    *input;
  2505. {
  2506.     char    *result = (char *) 0;
  2507.  
  2508.     malloc_strcpy(&result, FromUserHost ? FromUserHost : empty_string);
  2509.     return result;
  2510. }
  2511.  
  2512. char    *
  2513. function_strip(input)
  2514.     char    *input;
  2515. {
  2516.     static    char    FAR result[BIG_BUFFER_SIZE+1] = "";
  2517.     char    *retval = (char *) 0;
  2518.     char    *chars;
  2519.     char    *cp, *dp;
  2520.  
  2521.     if ((chars = next_arg(input, &input)) && input)
  2522.     {
  2523.         for (cp = input, dp = result; *cp; cp++)
  2524.         {
  2525.             if (!index(chars, *cp))
  2526.                 *dp++ = *cp;
  2527.         }
  2528.         *dp = '\0';
  2529.     }
  2530.     malloc_strcpy(&retval, result);
  2531.     return retval;
  2532. }
  2533.  
  2534. char    *
  2535. function_encode(input)
  2536.     unsigned char    *input;
  2537. {
  2538.     static unsigned char    FAR result[BIG_BUFFER_SIZE+1] = "";
  2539.     char    *retval = (char *) 0;
  2540.     unsigned char    *c;
  2541.     int    i = 0;
  2542.  
  2543.     for (c = input; *c; c++)
  2544.     {
  2545.         result[i++] = (*c >> 4) + 0x41;
  2546.         result[i++] = (*c & 0x0f) + 0x41;
  2547.     }
  2548.     result[i] = '\0';
  2549.     malloc_strcpy(&retval, result);
  2550.     return retval;
  2551. }
  2552.  
  2553.  
  2554. char    *
  2555. function_decode(input)
  2556.     unsigned char    *input;
  2557. {
  2558.     static unsigned    char    FAR result[BIG_BUFFER_SIZE+1] = "";
  2559.     char    *retval = (char *) 0;
  2560.     unsigned char    *c;
  2561.     unsigned char    d,e;
  2562.     int    i = 0;
  2563.  
  2564.     c = input;
  2565.     while((d = *c) && (e = *(c+1)))
  2566.     {
  2567.         result[i] = ((d - 0x41) << 4) | (e - 0x41);
  2568.         c += 2;
  2569.         i++;
  2570.     }
  2571.     result[i] = '\0';
  2572.     malloc_strcpy(&retval, result);
  2573.     return retval;
  2574. }
  2575.  
  2576. char    *
  2577. function_ischannel(input)
  2578.     char    *input;
  2579. {
  2580.     char    *result = (char *) 0;
  2581.  
  2582.     malloc_strcpy(&result, is_channel(input) ? "1" : "0");
  2583.     return result;
  2584. }
  2585.  
  2586. char    *
  2587. function_ischanop(input)
  2588.     char    *input;
  2589. {
  2590.     char    *result = (char *) 0;
  2591.     char    *nick;
  2592.     char    *channel = NULL;
  2593.  
  2594.     if (!(nick = next_arg(input, &channel)))
  2595.         malloc_strcpy(&result, "0");
  2596.     else
  2597.         malloc_strcpy(&result, is_chanop(channel, nick) ? "1" : "0");
  2598.     return result;
  2599. }
  2600.  
  2601.  
  2602. char    *
  2603. function_word(input)
  2604.     char    *input;
  2605. {
  2606.     char    *result = (char *) 0;
  2607.     char    *count;
  2608.     int    cvalue;
  2609.     char    *word;
  2610.  
  2611.     count = next_arg(input, &input);
  2612.     if (count)
  2613.         cvalue = atoi(count);
  2614.     else
  2615.         cvalue = 0;
  2616.     if (cvalue < 0)
  2617.         malloc_strcpy(&result, empty_string);
  2618.     else
  2619.     {
  2620.         for (word = next_arg(input, &input); word && cvalue--;
  2621.                 word = next_arg(input, &input))
  2622.             ;
  2623.         malloc_strcpy(&result, (word) ? word : empty_string);
  2624.     }
  2625.     return result;
  2626. }
  2627.  
  2628.  
  2629. char    *
  2630. function_winnum(input)
  2631.     char    *input;
  2632. {
  2633.     char    *result = (char *) 0;
  2634.     char    tmp[10];
  2635.  
  2636.     if (curr_scr_win)
  2637.         sprintf(tmp, "%d", curr_scr_win->refnum);
  2638.     else
  2639.         strcpy(tmp, "-1");
  2640.     malloc_strcpy(&result, tmp);
  2641.     return result;
  2642. }
  2643.  
  2644. char    *
  2645. function_winnam(input)
  2646.     char    *input;
  2647. {
  2648.     char    *result = (char *) 0;
  2649.  
  2650.     malloc_strcpy(&result, (curr_scr_win && curr_scr_win->name) ?
  2651.         curr_scr_win->name : empty_string);
  2652.     return result;
  2653. }
  2654.  
  2655. char    *
  2656. function_connect(input)
  2657.     char    *input;
  2658. {
  2659.     char    *result = (char *) 0;
  2660.     char    *host;
  2661.  
  2662. #ifdef DAEMON_UID
  2663.     if (getuid() == DAEMON_UID)
  2664.         put_it("You are not permitted to use CONNECT()");
  2665.     else
  2666. #endif
  2667.         if ((host = next_arg(input, &input)) != NULL)
  2668.             result = dcc_raw_connect(host, atoi(input));
  2669.     return result;
  2670. }
  2671.  
  2672.  
  2673. char    *
  2674. function_listen(input)
  2675.     char    *input;
  2676. {
  2677.     char    *result = (char *) 0;
  2678.  
  2679. #ifdef DAEMON_UID
  2680.     if (getuid() == DAEMON_UID)
  2681.         malloc_strcpy(&result, "0");
  2682.     else
  2683. #endif
  2684.         result = dcc_raw_listen(atoi(input));
  2685.     return result;
  2686. }
  2687.  
  2688. static    char    *
  2689. alias_version(input)
  2690.     char    *input;
  2691. {
  2692.     char *result = (char *) 0;
  2693.     malloc_strcpy(&result, internal_version);
  2694.     return result;
  2695. }
  2696.  
  2697. static    char    *
  2698. alias_currdir(input)
  2699.     char    *input;
  2700. {
  2701.     char    *result = (char *) 0;
  2702.  
  2703.         getcwd(buffer, BIG_BUFFER_SIZE+1);
  2704.     /* is this more portable? *shrug*. i chose BIG_BUFFER_SIZE+1
  2705.        because it's more readable -cgw- */
  2706.     /* getcwd((char *)buffer, sizeof((char *)buffer)); */
  2707.     malloc_strcpy(&result, buffer);
  2708.     return result;
  2709. }
  2710.  
  2711. static    char    *
  2712. alias_current_numeric(input)
  2713.     char    *input;
  2714. {
  2715.     char    *result = (char *) 0,
  2716.         number[4];
  2717.     
  2718.     sprintf(number, "%03d", -current_numeric);
  2719.     malloc_strcpy(&result, number);
  2720.     return result;
  2721. }
  2722.  
  2723. static    char    *
  2724. alias_server_version(input)
  2725.     char    *input;
  2726. {
  2727.     char    *result = (char *) 0,
  2728.         *s;
  2729.  
  2730.     malloc_strcpy(&result,
  2731.         (s = server_list[curr_scr_win->server].version_string) ?
  2732.                 s : empty_string);
  2733.     return result;
  2734. }
  2735.  
  2736. char    *
  2737. function_toupper(input)
  2738.     char    *input;
  2739. {
  2740.     char    *new = (char *) 0,
  2741.         *ptr;
  2742.  
  2743.     if (!input)
  2744.         return empty_string;
  2745.     malloc_strcpy(&new, input);
  2746.     for (ptr = new; *ptr; ptr++)
  2747.         *ptr = islower(*ptr) ? toupper(*ptr) : *ptr;
  2748.     return new;
  2749. }
  2750.  
  2751. char    *
  2752. function_tolower(input)
  2753.     char    *input;
  2754. {
  2755.     char    *new = (char *) 0,
  2756.         *ptr;
  2757.  
  2758.     if (!input)
  2759.         return empty_string;
  2760.     malloc_strcpy(&new, input);
  2761.     for (ptr = new; *ptr; ptr++)
  2762.         *ptr = (isupper(*ptr)) ? tolower(*ptr) : *ptr;
  2763.     return new;
  2764. }
  2765.  
  2766. char    *
  2767. function_curpos(input)
  2768.     char    *input;
  2769. {
  2770.     char    *new = (char *) 0,
  2771.         pos[4];
  2772.  
  2773.     sprintf(pos, "%d", current_screen->buffer_pos);
  2774.     malloc_strcpy(&new, pos);
  2775.     return new;
  2776. }
  2777.  
  2778. char    *
  2779. function_channels(input)
  2780.     char    *input;
  2781. {
  2782.     Window    *window;
  2783.  
  2784.     if (input)
  2785.         window = isdigit(*input) ? get_window_by_refnum(atoi(input))
  2786.                      : curr_scr_win;
  2787.     else
  2788.         window = curr_scr_win;
  2789.  
  2790.     return create_channel_list(window);
  2791. }
  2792.  
  2793. char    *
  2794. function_servers(input)
  2795.     char    *input;
  2796. {
  2797.     return create_server_list();
  2798. }
  2799.  
  2800. char    *
  2801. function_onchannel(input)
  2802.     char    *input;
  2803. {
  2804.     char    *result = (char *) 0;
  2805.     char    *nick;
  2806.     char    *channel = NULL;
  2807.  
  2808.     if (!(nick = next_arg(input, &channel)))
  2809.         malloc_strcpy(&result, "0");
  2810.     else
  2811.         malloc_strcpy(&result, is_on_channel(channel, nick) ? "1"
  2812.                                     : "0");
  2813.     return result;
  2814. }
  2815.  
  2816. char    *
  2817. function_pid(input)
  2818.     char    *input;
  2819. {
  2820.     char    *result = (char *) 0;
  2821.  
  2822.     sprintf(buffer, "%d", (int) getpid());
  2823.     malloc_strcpy(&result, buffer);
  2824.     return result;
  2825. }
  2826.  
  2827. char    *
  2828. function_ppid(input)
  2829.     char    *input;
  2830. {
  2831.     char    *result = (char *) 0;
  2832.  
  2833.     sprintf(buffer, "%d", (int) getppid());
  2834.     malloc_strcpy(&result, buffer);
  2835.     return result;
  2836. }
  2837.  
  2838. char    *
  2839. function_chanusers(input)
  2840.     char    *input;
  2841. {
  2842.     ChannelList    *chan;
  2843.     NickList    *nicks;
  2844.     char    *result = (char *) 0;
  2845.  
  2846.     chan = lookup_channel(from_server, input, 0);
  2847.     if ((ChannelList *) 0 == chan)
  2848.         return (char *) 0;
  2849.  
  2850.     for (nicks = chan->nicks; nicks; nicks = nicks->next)
  2851.     {
  2852.         strcat(buffer, " ");
  2853.         strcat(buffer, nicks->nick);
  2854.     }
  2855.     malloc_strcpy(&result, buffer + 1);
  2856.     return result;
  2857. }
  2858.  
  2859.  
  2860. /*
  2861.  * strftime() patch from hari (markc@arbld.unimelb.edu.au)
  2862.  */
  2863. char    *
  2864. function_strftime(input)
  2865.     char     *input;
  2866. {
  2867.     char    result[128];
  2868.     time_t    ltime;
  2869.     char    *fmt = (char *) 0;
  2870.  
  2871.     ltime = atol(input);
  2872.     fmt = input;
  2873.     /* skip the time field */
  2874.     while (isdigit(*fmt))
  2875.         ++fmt; 
  2876.     if (*fmt && *++fmt)
  2877.     {
  2878.         struct tm    *tm;
  2879.  
  2880.         tm = localtime(<ime);
  2881.         if (strftime(result, 128, fmt, tm))
  2882.         {
  2883.             char *    s = (char *) 0;
  2884.  
  2885.             malloc_strcpy(&s, result);
  2886.             return s;
  2887.         }
  2888.         else
  2889.             return (char *) 0;
  2890.     }
  2891.     else
  2892.     {
  2893.         return (char *) 0;
  2894.     }
  2895. }
  2896.